/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.repository.dac;

import com.inspur.edp.cef.api.repository.DbParameter;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.NodeSortInfo;
import com.inspur.edp.cef.entity.condition.RetrieveFilter;
import com.inspur.edp.cef.entity.condition.SortCondition;
import com.inspur.edp.cef.entity.entity.IChildEntityData;
import com.inspur.edp.cef.repository.adaptor.AdaptorRetrieveParam;
import com.inspur.edp.cef.repository.adaptor.EntityRelationalAdaptor;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfo;
import com.inspur.edp.cef.repository.exception.CefRepositoryException;

import java.sql.SQLException;
import java.util.*;

public abstract class ChildEntityDac extends EntityDac {
    @Override
    protected final String getCacheConfigID() {
        return "";
    }

    @Override
    protected final boolean getUseDataCache() {
        return false;
    }

    @Override
    public Map<String, Object> getPars() {
        if (pars == null) {
            return getParentDac().getPars();
        }
        return pars;
    }

    @Override
    public java.util.HashMap<String, String> getVars() {
        if (getParentDac() != null) {
            return getParentDac().getVars();
        }
        return getVars();
    }

    private EntityDac privateParentDac;

    protected final EntityDac getParentDac() {
        return privateParentDac;
    }

    protected ChildEntityDac(EntityDac parentDac) {
        privateParentDac = parentDac;
    }

    public final Map<String, List<IChildEntityData>> getDataByParents(String parentJoinInfo, String condition
            , java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias, List<DbParameter> dbPars) {
        return getDataByParents(parentJoinInfo, condition, orderByConditon, tableAlias, dbPars, null);
    }

    public final Map<String, List<IChildEntityData>> getDataByParents(String parentJoinInfo, String condition
            , java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias, List<DbParameter> dbPars, EntityFilter filter) {
        return this.getDataByParentsWithPara(parentJoinInfo, condition, orderByConditon, tableAlias, dbPars, null);
    }

    /**
     * 批量检索从表
     * @param parentJoinInfo
     * @param condition
     * @param orderByConditon
     * @param tableAlias
     * @param dbPars
     * @param adaptorRetrieveParam
     * @return
     */
    public final Map<String, List<IChildEntityData>> getDirectChildDataByParentsWithPara(String parentJoinInfo, List<String> condition
            , List<String> dataIds, java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias,
                                                                              List<DbParameter> dbPars,
                                                                              AdaptorRetrieveParam adaptorRetrieveParam) {
        String parentAlias = getParentDac().getEntityAdaptor().getWrappedTableAlias();
        if (!tableAlias.contains(parentAlias)) {
            tableAlias.add(parentAlias);
        }

        java.util.ArrayList<SortCondition> sorts = null;
        if (orderByConditon != null && orderByConditon.size() > 0) {
            for (NodeSortInfo order : orderByConditon) {
                if (this.getNodeCode().equals(order.getNodeCode())) {
                    sorts = order.getSortConditions();
                }
            }
        }
        List<String> parentIdCondition = getEntityAdaptor().getBatchInParentIDsFilter(dataIds);
        java.util.List<IChildEntityData> currentDatas =
                getDataWithParentJoinIds("", parentIdCondition, sorts,
                        tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
        if (currentDatas == null || currentDatas.isEmpty()) {
            return null;
        }
        RetrieveFilter retrieveFilter =adaptorRetrieveParam.getRetrieveFilter();
        for (ChildEntityDac childDac : innerGetChildDacList()) {
            if(retrieveFilter!=null&&retrieveFilter.isOnlyRetrieveSomeChilds()&& retrieveFilter.isCanExcludedChilds() && !retrieveFilter.getRetrieveChildNodeList().contains(childDac.getNodeCode()))
                continue;
            Map<String, List<IChildEntityData>> childData =
                    childDac.getDataByParentsWithPara(getParentJoin() + " " + parentJoinInfo, condition,
                            orderByConditon, tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
            if (childData == null || childData.size() == 0) {
                continue;
            }
            super.mergeChildDatas(childDac.getNodeCode(), convertToEntityDataList(currentDatas), childData);

        }
        Map<String, List<IChildEntityData>> map = new HashMap<>();
        for (IChildEntityData data :
                currentDatas) {
            if (map.containsKey(data.getParentID())) {
                List<IChildEntityData> childList = map.get(data.getParentID());
                childList.add(data);

            } else {
                List<IChildEntityData> childList = new ArrayList<>();
                map.put(data.getParentID(), childList);
                childList.add(data);
            }
        }
        return map;
    }

    public final Map<String, List<IChildEntityData>> getDataByParentsWithPara(String parentJoinInfo, List<String> condition
            , java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias,
                                                                              List<DbParameter> dbPars,
                                                                              AdaptorRetrieveParam adaptorRetrieveParam) {
        String parentAlias = getParentDac().getEntityAdaptor().getWrappedTableAlias();
        if (!tableAlias.contains(parentAlias)) {
            tableAlias.add(parentAlias);
        }

        java.util.ArrayList<SortCondition> sorts = null;
        if (orderByConditon != null && orderByConditon.size() > 0) {
            for (NodeSortInfo order : orderByConditon) {
                if (this.getNodeCode().equals(order.getNodeCode())) {
                    sorts = order.getSortConditions();
                }
            }
        }
        java.util.List<IChildEntityData> currentDatas =
                getDataWithParentJoinIds(getParentJoin() + " " + parentJoinInfo, condition, sorts,
                        tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
        if (currentDatas == null || currentDatas.isEmpty()) {
            return null;
        }
        RetrieveFilter retrieveFilter =adaptorRetrieveParam.getRetrieveFilter();
        for (ChildEntityDac childDac : innerGetChildDacList()) {
            if(retrieveFilter!=null&&retrieveFilter.isOnlyRetrieveSomeChilds()&& retrieveFilter.isCanExcludedChilds() && !retrieveFilter.getRetrieveChildNodeList().contains(childDac.getNodeCode()))
                continue;
            Map<String, List<IChildEntityData>> childData =
                    childDac.getDataByParentsWithPara(getParentJoin() + " " + parentJoinInfo, condition,
                            orderByConditon, tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
            if (childData == null || childData.size() == 0) {
                continue;
            }
            super.mergeChildDatas(childDac.getNodeCode(), convertToEntityDataList(currentDatas), childData);

        }
        Map<String, List<IChildEntityData>> map = new HashMap<>();
        for (IChildEntityData data :
                currentDatas) {
            if (map.containsKey(data.getParentID())) {
                List<IChildEntityData> childList = map.get(data.getParentID());
                childList.add(data);

            } else {
                List<IChildEntityData> childList = new ArrayList<>();
                map.put(data.getParentID(), childList);
                childList.add(data);
            }
        }
        return map;
    }


    /**
     *
     * @param parentJoinInfo
     * @param condition        where mainTable.Id = ?0
     * @param orderByConditon
     * @param tableAlias
     * @param dbPars  主表的绑定参数信息
     * @param adaptorRetrieveParam
     * @return
     */
    public final Map<String, List<IChildEntityData>> getDirectChildDataByParentsWithPara(String parentJoinInfo, String condition
            , java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias,
                                                                              List<DbParameter> dbPars,
                                                                              AdaptorRetrieveParam adaptorRetrieveParam) {
        String parentAlias = getParentDac().getEntityAdaptor().getWrappedTableAlias();
        if (!tableAlias.contains(parentAlias)) {
            tableAlias.add(parentAlias);
        }

        java.util.ArrayList<SortCondition> sorts = null;
        if (orderByConditon != null && orderByConditon.size() > 0) {
            for (NodeSortInfo order : orderByConditon) {
                if (this.getNodeCode().equals(order.getNodeCode())) {
                    sorts = order.getSortConditions();
                }
            }
        }

        //直接从表 去掉Join信息   条件:where childTable.ParentId = ?0
        DbColumnInfo parentIdInfo = getEntityAdaptor().getParentIdColumnInfo();
        if(parentIdInfo == null){
            StringBuilder sb = new StringBuilder();
            sb.append("当前表:" + getEntityAdaptor().getTableAlias() + "没有找到ParentId字段,请确认!");
            throw new CefRepositoryException(sb.toString());
        }
        String parentIdCondition = String.format(" where %1$s.%2$s=", getEntityAdaptor().getTableAlias(), parentIdInfo.getDbColumnName()) + "?0";
        List<DbParameter> parIdParameters=new ArrayList<>();
        parIdParameters.add( getEntityAdaptor().buildParam(parentIdInfo.getColumnName(),parentIdInfo.getColumnType(), dbPars.get(0).getValue()));
        java.util.List<IChildEntityData> currentDatas =
                getDataWithParentJoinIds("", parentIdCondition, sorts,
                        tableAlias, parIdParameters, adaptorRetrieveParam);
        if (currentDatas == null || currentDatas.isEmpty()) {
            return null;
        }
        //检索从从表数据
        RetrieveFilter retrieveFilter=adaptorRetrieveParam.getRetrieveFilter();
        for (ChildEntityDac childDac : innerGetChildDacList()) {
            if(retrieveFilter!=null&&retrieveFilter.isOnlyRetrieveSomeChilds()&& retrieveFilter.isCanExcludedChilds() && !retrieveFilter.getRetrieveChildNodeList().contains(childDac.getNodeCode()))
                continue;
            Map<String, List<IChildEntityData>> childData =
                    childDac.getDataByParentsWithPara(getParentJoin() + " " + parentJoinInfo, condition,
                            orderByConditon, tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
            if (childData == null || childData.size() == 0) {
                continue;
            }
            super.mergeChildDatas(childDac.getNodeCode(), convertToEntityDataList(currentDatas), childData);

        }
        Map<String, List<IChildEntityData>> map = new HashMap<>();
        for (IChildEntityData data :
                currentDatas) {
            if (map.containsKey(data.getParentID())) {
                List<IChildEntityData> childList = map.get(data.getParentID());
                childList.add(data);

            } else {
                List<IChildEntityData> childList = new ArrayList<>();
                map.put(data.getParentID(), childList);
                childList.add(data);
            }
        }
        return map;
    }


    public final Map<String, List<IChildEntityData>> getDataByParentsWithPara(String parentJoinInfo, String condition
            , java.util.ArrayList<NodeSortInfo> orderByConditon, java.util.ArrayList<String> tableAlias,
                                                                              List<DbParameter> dbPars,
                                                                              AdaptorRetrieveParam adaptorRetrieveParam) {
        String parentAlias = getParentDac().getEntityAdaptor().getWrappedTableAlias();
        if (!tableAlias.contains(parentAlias)) {
            tableAlias.add(parentAlias);
        }

        java.util.ArrayList<SortCondition> sorts = null;
        if (orderByConditon != null && orderByConditon.size() > 0) {
            for (NodeSortInfo order : orderByConditon) {
                if (this.getNodeCode().equals(order.getNodeCode())) {
                    sorts = order.getSortConditions();
                }
            }
        }
        java.util.List<IChildEntityData> currentDatas =
                getDataWithParentJoinIds(getParentJoin() + " " + parentJoinInfo, condition, sorts,
                        tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
        if (currentDatas == null || currentDatas.isEmpty()) {
            return null;
        }
        RetrieveFilter retrieveFilter=adaptorRetrieveParam.getRetrieveFilter();
        for (ChildEntityDac childDac : innerGetChildDacList()) {
            if(retrieveFilter!=null&&retrieveFilter.isOnlyRetrieveSomeChilds()&& retrieveFilter.isCanExcludedChilds() && !retrieveFilter.getRetrieveChildNodeList().contains(childDac.getNodeCode()))
                continue;
            Map<String, List<IChildEntityData>> childData =
                    childDac.getDataByParentsWithPara(getParentJoin() + " " + parentJoinInfo, condition,
                            orderByConditon, tableAlias, tryCopyPars(dbPars), adaptorRetrieveParam);
            if (childData == null || childData.size() == 0) {
                continue;
            }
            super.mergeChildDatas(childDac.getNodeCode(), convertToEntityDataList(currentDatas), childData);

        }
        Map<String, List<IChildEntityData>> map = new HashMap<>();
        for (IChildEntityData data :
                currentDatas) {
            if (map.containsKey(data.getParentID())) {
                List<IChildEntityData> childList = map.get(data.getParentID());
                childList.add(data);

            } else {
                List<IChildEntityData> childList = new ArrayList<>();
                map.put(data.getParentID(), childList);
                childList.add(data);
            }
        }
        return map;
    }

    protected final List<DbParameter> tryCopyPars(List<DbParameter> dbPars) {
        if (dbPars == null || dbPars.size() == 0) {
            return dbPars;
        }
        List<DbParameter> rez = new ArrayList<DbParameter>();
        for (DbParameter param : dbPars) {
            rez.add(param.Clone());
        }
        return rez;
    }

    private java.util.List<IChildEntityData> getDataWithParentJoinIds(String joinInfo, List<String> condition, java.util.ArrayList<SortCondition> orderByConditon
            , java.util.ArrayList<String> tableAlias, List<DbParameter> dbPars, AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityRelationalAdaptor adapter = getEntityAdaptor();
        adapter.initParams(getPars());
        adapter.initVars(getVars());
        return adapter.getDataWithParentJoinIds(joinInfo, condition, orderByConditon, tableAlias,
                dbPars, adaptorRetrieveParam);
    }

    private java.util.List<IChildEntityData> getDataWithParentJoinIds(String joinInfo, String condition, java.util.ArrayList<SortCondition> orderByConditon
            , java.util.ArrayList<String> tableAlias, List<DbParameter> dbPars, AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityRelationalAdaptor adapter = getEntityAdaptor();
        adapter.initParams(getPars());
        adapter.initVars(getVars());
        return adapter.getDataWithParentJoinIds(joinInfo, condition, orderByConditon, tableAlias,
                dbPars, adaptorRetrieveParam);
    }

    /**
     * JOIN PerfTestTestChild TestChild ON testSunzi.ParentID = TestChild.ID
     * JOIN 主表 主 on 从表.ParentID = 主.ID
     * @return
     */
    protected String getParentJoin() {
        return getEntityAdaptor().getParentJoin().replace("@ParentTableName@", getParentDac().getEntityAdaptor().innerGetTableName())
                .replace("@ParentTableAlias@", getParentDac().getEntityAdaptor().getWrappedTableAlias())
                .replace("@PrimaryID@",getParentDac().getEntityAdaptor().getWrappedTableAlias() + "." +getParentDac().getEntityAdaptor().getPrimaryKey());
    }

    //endregion

    //region DeleteByParentId
    public void deleteByParent(String parentJoinInfo, String filter, List<DbParameter> dbPars) throws SQLException {
        deleteChildren(getParentJoin() + " " + parentJoinInfo, filter, dbPars);
        getEntityAdaptor().deleteByParent(getParentJoin() + " " + parentJoinInfo, filter, dbPars);
    }

    // endregion
}
